﻿/*
** Xin YUAN, 2023, BSD (2)
*/

////////////////////////////////////////////////////////////////////////////////

//sync_mutex

class sync_mutex
{
public:
	sync_mutex() noexcept : m_bInitialized(false)
	{
	}
	sync_mutex(const sync_mutex&) = delete;
	~sync_mutex() noexcept
	{
		Term();
	}

	sync_mutex& operator=(const sync_mutex&) = delete;

	bool IsValid() const noexcept
	{
		return m_bInitialized;
	}

	bool Init() noexcept
	{
		assert( !IsValid() );
		if ( !::InitializeCriticalSectionEx(&m_sect, 2000, 0) )
			return false;
		m_bInitialized = true;
		return true;
	}
	void Term() noexcept
	{
		if ( m_bInitialized ) {
			::DeleteCriticalSection(&m_sect);
			m_bInitialized = false;
		}
	}

	void Lock() noexcept
	{
		assert( m_bInitialized );
		::EnterCriticalSection(&m_sect);
	}
	void Unlock() noexcept
	{
		assert( m_bInitialized );
		::LeaveCriticalSection(&m_sect);
	}

private:
	CRITICAL_SECTION m_sect;
	bool m_bInitialized;

private:
	friend class sync_condition;
};

//sync_condition

class sync_condition
{
public:
	sync_condition() noexcept : m_bInitialized(false)
	{
	}
	sync_condition(const sync_condition&) = delete;
	~sync_condition() noexcept
	{
	}

	sync_condition& operator=(const sync_condition&) = delete;

	void Init() noexcept
	{
		assert( !m_bInitialized );
		::InitializeConditionVariable(&m_cv);
		m_bInitialized = true;
	}

	void Wait(sync_mutex& mtx) noexcept
	{
		assert( m_bInitialized );
		BOOL bRet = ::SleepConditionVariableCS(&m_cv, &(mtx.m_sect), INFINITE);
		assert( bRet );
	}
	void Signal() noexcept
	{
		assert( m_bInitialized );
		::WakeConditionVariable(&m_cv);
	}

private:
	CONDITION_VARIABLE m_cv;
	bool m_bInitialized;
};

////////////////////////////////////////////////////////////////////////////////
